package workerwithdb.managers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import workerwithdb.dao.HibernateDAOGarage;
import workerwithdb.dao.HibernateDAOMaster;
import workerwithdb.dao.HibernateDAOOrder;
import workerwithdb.hibernateutil.HibernateUtil;
import api.entitites.IGarage;
import api.entitites.IMaster;
import api.entitites.IOrder;
import api.entitites.OrderStatus;
import autoproperties.AutoProperties;
import entitiesfactory.EntitiesFactory;
import exportimporterentities.ExportImportEntities;

public class DBManager {

	private HibernateDAOOrder daoOrder = new HibernateDAOOrder();
	private HibernateDAOGarage daoGarage = new HibernateDAOGarage();
	private HibernateDAOMaster daoMaster = new HibernateDAOMaster();
	private HibernateUtil hibernateUtil = HibernateUtil.getInstance();
	private EntitiesFactory entitiesFactory = EntitiesFactory.getInstance();
	private AutoProperties autoProperties = AutoProperties.getInstance();
	private ExportImportEntities exportImportEntities = new ExportImportEntities();
	
	private Logger log = Logger.getLogger(DBManager.class);
	
	private Session getSession(){
		Session session = hibernateUtil.getSessionFactory().getCurrentSession();
		return session;
	}

	private Transaction getTransaction(Session session){
		Transaction transaction = session.beginTransaction();
		return transaction;
	}
	
	private void exceptionActivity(Exception e,Transaction transaction){
		log.error(e);
		transaction.rollback();
	}
	
	
	public Long getEmptyPlaces() throws Exception{
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			Long places = daoGarage.getEmptyGarage(session);	
			transaction.commit();
			return places;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public IOrder getOrderByMaster(String masterName) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IOrder order = daoMaster.getOrderByMaster(masterName,session);
			transaction.commit();
			return order;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public IMaster getMasterByOrder(Integer orderNumber) throws Exception{
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			IMaster master = daoOrder.getMasterByOrder(orderNumber,session);
			transaction.commit();
			return master;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Long getEmptyPlacesOnDate(Date date) throws Exception{
		Session session = getSession();
		Transaction transaction = session.beginTransaction();
		try {
			Long countGarage = daoGarage.getEmptyGaragesOnDate(date,session);
			Long countMaster = daoMaster.getEmptyMastersOnDate(date,session);
			transaction.commit();
			Long count = null;
			if (countGarage == 0 || countMaster == 0) {
				count = (long) 0;
			} else if (countMaster > countGarage) {
				count = countGarage;
			} else if (countMaster < countGarage) {
				count = countMaster;
			} else {
				count = countGarage;
			}
			return count;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public Date getNextFreeDate() throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			Date date = daoOrder.getNextFreeDate(session);
			transaction.commit();
			return date;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IOrder> sortAllOrder(SortOrdersBy sortBy) throws Exception{
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder =  daoOrder.sortAllOrders(sortBy,session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	public List<IMaster> sortMaster(SortMastersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IMaster> listMaster = daoMaster.sortMasters(sortBy,session);
			transaction.commit();
			return listMaster;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	

	public List<IOrder> sortMadingOrder(SortOrdersBy sortBy) throws Exception {
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder = daoOrder.sortMadingOrders(sortBy,session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	

	public List<IOrder> sortOrderByPeriod(OrderStatus ordSt,Date begin,
			Date end,SortOrdersBy sortBy) throws Exception{
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try {
			List<IOrder> listOrder = daoOrder.sortOrdersByPeriod(begin, end,
					sortBy, ordSt,session);
			transaction.commit();
			return listOrder;
		} catch (HibernateException he) {
			exceptionActivity(he, transaction);
			return null;
		}
	}

	
	public Boolean addMaster(String masterName) throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
		IMaster master = (IMaster) entitiesFactory.getObject(IMaster.class);
		master.setName(masterName);
		daoMaster.save(master, session);;
		answer = true;
		transaction.commit();
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean deleteMaster(String masterName) throws Exception{
		Boolean answer =  false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
		IMaster master = daoMaster.readMaster(masterName,session);
		daoMaster.delete(master, session);
		transaction.commit();
		answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;		
	}
	
	public Boolean addGarage(Integer numberGarage) throws Exception{
		Boolean answer = false;
		Session session =  getSession();
		Transaction transaction = getTransaction(session);
		try{
		if (autoProperties.getGarageManager() == true) {
			IGarage garage = (IGarage) entitiesFactory.getObject(IGarage.class);
			garage.setNumber(numberGarage);
			daoGarage.save(garage, session);
			transaction.commit();
			answer = true;
		}
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;		
	}
	
	
	public Boolean deleteGarage(Integer numberGarage)throws Exception {
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
		if (autoProperties.getGarageManager() == true) {
			IGarage garage = daoGarage.readGarage(numberGarage, session);
			daoGarage.delete(garage, session);
			transaction.commit();
			answer = true;			
		}
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	
	public Boolean addOrder(Integer orderNumber, Date fillingDate,Date deadlineDate, Date beginingDate, Integer price,String masterName, Integer numberGarage) throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			IOrder order = (IOrder) entitiesFactory.getObject(IOrder.class);
			IMaster master = daoMaster.readMaster(masterName,session);
			IGarage garage = daoGarage.readGarage(numberGarage,session);
			order.setNumber(orderNumber);
			order.setPrice(price);
			order.setBeginingDate(beginingDate);
			order.setDeadlineDate(deadlineDate);
			order.setFillingDate(fillingDate);
			order.setMaster(master);
			master.setEmployment(true);
			order.setGarage(garage);
			garage.setFullness(true);
			daoGarage.update(garage,session);
			daoMaster.update(master,session);
			daoOrder.save(order, session);;
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}

	
	public Boolean markOrder(Integer numberOrder,OrderStatus orderStatus) throws  Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
		IOrder order = daoOrder.readOrder(numberOrder, session);
		IMaster master = order.getMaster();
		IGarage garage = order.getGarage();
		master.setEmployment(false);
		garage.setFullness(false);
		order.setOrderStatus(orderStatus);
		daoOrder.update(order,session);
		daoMaster.update(master,session);
		daoGarage.update(garage,session);
		transaction.commit();
		answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	
	public Boolean shiftOrdersDeadlineDate(Date newDate,Integer numberOrder)throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
				if (autoProperties.getPermissionShiftTimeOrder()) {
				IOrder order = daoOrder.readOrder(numberOrder,session);
				order.setDeadlineDate(newDate);
				daoOrder.update(order,session);
				answer = true;
				transaction.commit();
			}
		}catch(HibernateException he){
			exceptionActivity(he, transaction);	
		}		
		return answer;
	}
	
	
	public Boolean cloneOrder(Integer number) throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{			
			IOrder order = daoOrder.readOrder(number,session);
			IOrder clone = order.cloneOrder();
			Long numberClone = daoOrder.getMaxNumberOrder(session)+1;
			String s = numberClone.toString();
			clone.setNumber(Integer.parseInt(s));
			transaction.commit(); 
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	
	public Boolean exportGarages() throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{			
		List<IGarage> garageList = daoGarage.getAll(session);
		exportImportEntities.ExportGarages(garageList);
		transaction.commit();
		answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean exportMasters()throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			List<IMaster> masterList = daoMaster.getAll(session);
			exportImportEntities.ExportMasters(masterList);
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean exportOrders()throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			List<IOrder> orderList = daoOrder.getAll(session);
			exportImportEntities.ExportOrders(orderList);
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean importGarages()throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			ArrayList<IGarage> garageList = exportImportEntities.ImportGarages();
			daoGarage.insertAllGarages(garageList,session);
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean importMasters()throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			ArrayList<IMaster> masterList = exportImportEntities.ImportMasters();
			daoMaster.insertAllMasters(masterList,session);
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	public Boolean importOrders()throws Exception{
		Boolean answer = false;
		Session session = getSession();
		Transaction transaction = getTransaction(session);
		try{
			ArrayList<IOrder> orderList = exportImportEntities.ImportOrders();
			daoOrder.insertAllOrders(orderList,session);
			transaction.commit();
			answer = true;
		}catch(HibernateException he){
			exceptionActivity(he, transaction);
		}
		return answer;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}